package com.bg.rpc.server;

import com.bg.rpc.protocol.RPCRequest;
import com.bg.rpc.protocol.RPCResponse;
import com.bg.rpc.service.impl.IDiffImpl;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * @Auther: zhengshunzhi
 * @Date: 2018/8/24 22:17
 * @Description: 服务器的处理逻辑
 */
public class RPCServerHandler extends ChannelHandlerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(RPCServerHandler.class);

    private final Map<String, String> handlerMap;


    public RPCServerHandler(Map<String, String> handlerMap) {
        this.handlerMap = handlerMap;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RPCResponse response = new RPCResponse();
        RPCRequest request = (RPCRequest) msg;
        response.setRequestId(request.getRequestId());
        try {
            Object result = handle(request);
            response.setResult(result);
        } catch (Throwable t) {
            response.setError(t);
        }
        ctx.writeAndFlush(response);
    }

    /**
     * netty心跳机制
     *
     * @param:
     * @return:
     * @auther: bonree
     * @date: 2018/8/27 16:39
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.ALL_IDLE) {
                //清除超时会话
//                ChannelFuture writeAndFlush = ctx.writeAndFlush("you will close");
//                writeAndFlush.addListener(new ChannelFutureListener() {
//
//                    @Override
//                    public void operationComplete(ChannelFuture future) throws Exception {
//                        ctx.channel().close();
//                    }
//                });
                ctx.channel().close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    private Object handle(RPCRequest request) throws Throwable {
        String className = request.getClassName();
        String serviceBean = handlerMap.get(className);

        Class<?> serviceClass = Class.forName(serviceBean);
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();

        FastClass serviceFastClass = FastClass.create(serviceClass);
        FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);
        //serviceClass.newInstance()实例化这个类
        return serviceFastMethod.invoke(serviceClass.newInstance(), parameters);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        LOGGER.error("server caught exception", cause);
        ctx.close();
    }
}